package com.yiwyn.demo.scanner;

import com.yiwyn.demo.anno.Task;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.*;

@Slf4j
@Component
public class AnnotationScanner implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private ApplicationContext applicationContext;

    // 用于存储类名和方法名的数组
    private final Map<Integer, TaskNode> methodList = new HashMap<>();

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        log.info("初始化bean开始");
        // 获取所有 Bean 名称
        String[] beanNames = applicationContext.getBeanDefinitionNames();

        for (String beanName : beanNames) {
            // 获取 Bean 的类型
            Object bean = applicationContext.getBean(beanName);
            Class<?> beanClass = bean.getClass();

            // 获取所有声明的方法
            Method[] methods = beanClass.getDeclaredMethods();

            for (Method method : methods) {
                // 判断方法上是否有 @MyCustomAnnotation 注解
                if (method.isAnnotationPresent(Task.class)) {
                    // 将类名和方法名存入数组
                    Task annotation = method.getAnnotation(Task.class);
                    TaskNode taskNode = new TaskNode();
                    taskNode.setMethod(method);
                    taskNode.setBean(bean);
                    taskNode.setHasParam(annotation.hasParam());
                    int key = annotation.apiCode();
                    if (methodList.containsKey(key)) {
                        throw new RuntimeException("@Task 重复定义apiCoce");
                    }
                    methodList.put(key, taskNode);
                }
            }
        }

        log.info("初始化bean结束");
    }

    // 获取方法名数组的方法
    public Map<Integer, TaskNode> getMethodNames() {
        return methodList;
    }

    @Data
    public static class TaskNode {
        private Boolean hasParam;
        private Object bean;
        private Method method;
    }

}
